package com.sds.sweng.swat.miplatform.service.pages;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Node;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;

import com.sds.sweng.swat.miplatform.service.figures.ServiceDesignAreaPane;
import com.sds.sweng.swat.miplatform.service.figures.components.ComplexComponent;
import com.sds.sweng.swat.miplatform.service.figures.components.SelectableComponent;
import com.sds.sweng.swat.miplatform.service.figures.components.ValidationComponent;
import com.sds.sweng.swat.miplatform.service.graphics.ComponentDrawer;

public class ServiceDesignArea extends Composite {

	private FigureCanvas canvas;
	private IFigure rootFigure;

	private MiplatformServicePage page;

	private Document sourceXml;

	private Map<String, ValidationComponent> validationComponents;

	public SelectableComponent previosSelectedComponent;
	public SelectableComponent currentSelectedComponent;

	public ComplexComponent selectedComplexComponent;

	private final int SCROLLBAR_WIDTH = 20;

	public ServiceDesignArea(MiplatformServicePage parent) {
		super(parent, SWT.NONE);
		page = parent;

		validationComponents = new HashMap<String, ValidationComponent>();

		initArea();
	}

	private void initArea() {
		setLayout(new FillLayout());

		canvas = new FigureCanvas(this, SWT.H_SCROLL | SWT.V_SCROLL);
		LightweightSystem lws = new LightweightSystem(canvas);
		rootFigure = new ServiceDesignAreaPane();

		canvas.setViewport(new Viewport(true));
		canvas.setScrollBarVisibility(FigureCanvas.ALWAYS);
		canvas.setContents(rootFigure);
		canvas.addControlListener(new ControlAdapter() {
			public void controlResized(ControlEvent e) {
				Rectangle clientArea = getClientArea();

				int width = Math.max(clientArea.width - SCROLLBAR_WIDTH, rootFigure.getMinimumSize().width);
				int height = Math.max(clientArea.height - SCROLLBAR_WIDTH, rootFigure.getMinimumSize().height);

				rootFigure.setSize(width, height);
			}
		});

		lws.setContents(canvas.getViewport());
	}

	public void display(Document sourceXml) {
		this.sourceXml = sourceXml;

		ComponentDrawer componentDrawer = new ComponentDrawer(rootFigure, this);

		Node formNode = sourceXml.selectSingleNode("/Window/Form");

		componentDrawer.drawAllComponents(formNode);
	}

	public void addValidationComponent(String id, ValidationComponent validationComponent) {
		validationComponents.put(id, validationComponent);
	}

	public ValidationComponent getValidationComponent(String id) {
		return validationComponents.get(id);
	}

	public List<ValidationComponent> getPartiedValidatioComponents(String serviceId) {
		List<ValidationComponent> partiedValidationComponents = new ArrayList<ValidationComponent>();
		Iterator<String> keys = validationComponents.keySet().iterator();

		while (keys.hasNext()) {
			String key = keys.next();
			ValidationComponent validationComponent = validationComponents.get(key);

			if (validationComponent.getValidationInfo(serviceId).partied) {
				addPartiedComponent(partiedValidationComponents, validationComponent);
			}
		}

		return partiedValidationComponents;
	}

	protected void addPartiedComponent(List<ValidationComponent> partiedComponents, ValidationComponent newComponent) {
		Point componentLocation = newComponent.getComponentLocation();

		for (int i=0;i<partiedComponents.size();i++) {
			Point partiedComponentLocation = partiedComponents.get(i).getComponentLocation();

			if (isForwardComponent(componentLocation, partiedComponentLocation)) {
				partiedComponents.add(i, newComponent);
				return;
			}
		}

		partiedComponents.add(newComponent);
	}

	protected boolean isForwardComponent(Point srcLocation, Point tgtLocation) {
		if (srcLocation.y < tgtLocation.y) {
			return true;
		} else if (srcLocation.y > tgtLocation.y) {
			return false;
		}

		if (srcLocation.x < tgtLocation.x) {
			return true;
		} else {
			return false;
		}
	}

	public void initValidationComponentStyle(String serviceId) {
		Iterator<String> keys = validationComponents.keySet().iterator();

		while (keys.hasNext()) {
			String key = keys.next();
			validationComponents.get(key).refresh(serviceId);
		}
	}

	public void setSelected(SelectableComponent selectedComponent) {
		page.setSelected(selectedComponent);
	}

}
